﻿// Decompiled with JetBrains decompiler
// Type: NetickEditor.NetickWindow
// Assembly: Netick.Unity.Editor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 0658BB4A-05C4-428D-9BD6-82E94959F5A1
// Assembly location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Editor\Netick.Unity.Editor.dll

using Netick.Unity;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine;
using UnityEngine.SceneManagement;

#nullable disable
namespace NetickEditor;

[ExecuteInEditMode]
[InitializeOnLoad]
public class NetickWindow : EditorWindow
{
  public const string Discord = "https://discord.com/invite/uV6bfG66Fx";
  public const string Pro = "https://www.patreon.com/user?u=82493081";
  public const string Docs = "https://www.netick.net/docs.html";
  public const string Site = "https://www.netick.net";
  internal static bool IsP = false;
  private NetickConfig _config;
  private NetworkConfigEditor _configEditor;
  private Texture _netickIcon;
  private Vector2 _scrollPosition;
  private Vector2 _scrollPositionSand;
  internal List<NetworkSandbox> _sandboxesCache = new List<NetworkSandbox>(4);
  internal static HashSet<string> _changedAssets = new HashSet<string>(32 /*0x20*/);
  private static List<NetworkObject> _cachedList = new List<NetworkObject>(32 /*0x20*/);

  [MenuItem("Tools/Netick/Settings", false, 111)]
  public static void ShowWindow() => EditorWindow.GetWindow<NetickWindow>(false, "Netick", true);

  [MenuItem("Tools/Netick/Discord")]
  public static void GoToDiscord() => Application.OpenURL("https://discord.com/invite/uV6bfG66Fx");

  [MenuItem("Tools/Netick/Get Pro")]
  public static void GoToPro() => Application.OpenURL("https://www.patreon.com/user?u=82493081");

  [MenuItem("Tools/Netick/Docs")]
  public static void GoToDocs() => Application.OpenURL("https://www.netick.net/docs.html");

  [MenuItem("Tools/Netick/Site")]
  public static void GoToSite() => Application.OpenURL("https://www.netick.net");

  private static int _selectedTab
  {
    get => SessionState.GetInt("Netick____SelectedTab", 0);
    set => SessionState.SetInt("Netick____SelectedTab", value);
  }

  public int callbackOrder => 1;

  private void OnEnable()
  {
    NetickWindow.IsP = NetworkConfigEditor.IsAssemblyLoaded("Netick.Pro");
    this._netickIcon = Resources.Load<Texture>("NetickBanner");
    this._config = NetickEditorUtils.GetConfig(true);
    if ((UnityEngine.Object) this._config != (UnityEngine.Object) null)
      this._configEditor = (NetworkConfigEditor) Editor.CreateEditor((UnityEngine.Object) this._config);
    this.titleContent = new GUIContent(EditorGUIUtility.IconContent("Settings"))
    {
      text = "Netick"
    };
  }

  static NetickWindow()
  {
    // ISSUE: method pointer
    ObjectChangeEvents.changesPublished += new ObjectChangeEvents.ObjectChangeEventsHandler((object) null, __methodptr(ChangesPublished));
    EditorApplication.playModeStateChanged += new Action<PlayModeStateChange>(NetickWindow.LogPlayModeState);
    // ISSUE: method pointer
    EditorApplication.update = (EditorApplication.CallbackFunction) Delegate.Combine((Delegate) EditorApplication.update, (Delegate) new EditorApplication.CallbackFunction((object) null, __methodptr(RunOnlyOnProjectLoad)));
    EditorApplication.hierarchyWindowItemOnGUI += new EditorApplication.HierarchyWindowItemCallback(NetickWindow.OnHierarchyGUI);
    NetickWindow.IsP = NetworkConfigEditor.IsAssemblyLoaded("Netick.Pro");
  }

  private static void RunOnlyOnProjectLoad()
  {
    try
    {
      if (!SessionState.GetBool("Netick___Init", false))
      {
        Debug.Log((object) "Netick Editor: initialized");
        NetickConfig config = NetickEditorUtils.GetConfig(true);
        if (config.AutoGetPrefabs)
          NetickPrefabTools.LoadAllNetworkedPrefabs(config);
        if (NetickEditorUtils.ShouldRecompile())
        {
          CompilationPipeline.RequestScriptCompilation((RequestScriptCompilationOptions) 1);
          Debug.Log((object) "Netick Editor: initial compilation");
        }
        SessionState.SetBool("Netick___Init", true);
      }
      try
      {
        NetickConfig config = NetickEditorUtils.GetConfig();
        if (config.Prefabs != null)
        {
          if (config.Prefabs.Count > 0)
          {
            for (int index = 0; index < config.Prefabs.Count; ++index)
            {
              NetworkObject prefab = config.Prefabs[index];
              if ((UnityEngine.Object) prefab == (UnityEngine.Object) null || (UnityEngine.Object) PrefabUtility.GetCorrespondingObjectFromOriginalSource<NetworkObject>(prefab) == (UnityEngine.Object) null)
              {
                Debug.Log((object) "Netick Editor: reload prefabs");
                NetickPrefabTools.LoadAllNetworkedPrefabs(config);
                break;
              }
            }
          }
        }
      }
      catch (Exception ex)
      {
        Debug.Log((object) "Netick Editor: updating prefabs failed");
      }
    }
    catch (Exception ex)
    {
      Debug.LogError((object) ex);
    }
    // ISSUE: method pointer
    EditorApplication.update = (EditorApplication.CallbackFunction) Delegate.Remove((Delegate) EditorApplication.update, (Delegate) new EditorApplication.CallbackFunction((object) null, __methodptr(RunOnlyOnProjectLoad)));
  }

  private void Update()
  {
    NetickConfig config = this._config;
    if ((UnityEngine.Object) config == (UnityEngine.Object) null)
      config = NetickEditorUtils.GetConfig();
    bool flag = false;
    if (NetickWindow._changedAssets.Count > 0)
    {
      string[] array = NetickWindow._changedAssets.ToArray<string>();
      foreach (string changedAsset in NetickWindow._changedAssets)
      {
        GameObject gameObject = AssetDatabase.LoadMainAssetAtPath(changedAsset) as GameObject;
        NetworkObject component;
        if ((UnityEngine.Object) gameObject != (UnityEngine.Object) null && gameObject.TryGetComponent<NetworkObject>(out component))
        {
          if (config.AutoGetPrefabs && changedAsset.IsSubPathOf(config.PrefabsPath) && !config.Prefabs.Contains(component))
          {
            flag = true;
            config.Prefabs.Add(component);
          }
          if (config.Prefabs.Contains(component))
          {
            flag = true;
            NetickPrefabTools.ProcessPrefab(component);
          }
        }
      }
      foreach (string str in array)
        NetickWindow._changedAssets.Remove(str);
    }
    if (config.AutoGetPrefabs)
    {
      foreach (NetworkObject prefab in config.Prefabs)
        NetickWindow._cachedList.Add(prefab);
      foreach (NetworkObject cached in NetickWindow._cachedList)
      {
        if ((UnityEngine.Object) cached == (UnityEngine.Object) null)
          config.Prefabs.Remove(cached);
      }
      NetickWindow._cachedList.Clear();
    }
    if (!flag)
      return;
    EditorUtility.SetDirty((UnityEngine.Object) config);
    AssetDatabase.SaveAssets();
    AssetDatabase.Refresh();
  }

  private static void ChangesPublished(ref ObjectChangeEventStream stream)
  {
    if (Application.isPlaying)
      return;
    bool flag = false;
    for (int index = 0; index < ((ObjectChangeEventStream) ref stream).length; ++index)
    {
      switch (((ObjectChangeEventStream) ref stream).GetEventType(index) - 2)
      {
        case 0:
          CreateGameObjectHierarchyEventArgs hierarchyEventArgs1;
          ((ObjectChangeEventStream) ref stream).GetCreateGameObjectHierarchyEvent(index, ref hierarchyEventArgs1);
          if ((UnityEngine.Object) (EditorUtility.InstanceIDToObject(((CreateGameObjectHierarchyEventArgs) ref hierarchyEventArgs1).instanceId) as GameObject).GetComponentInChildren<NetworkObject>() != (UnityEngine.Object) null)
          {
            flag = true;
            break;
          }
          break;
        case 1:
          ChangeGameObjectStructureHierarchyEventArgs hierarchyEventArgs2;
          ((ObjectChangeEventStream) ref stream).GetChangeGameObjectStructureHierarchyEvent(index, ref hierarchyEventArgs2);
          if ((UnityEngine.Object) (EditorUtility.InstanceIDToObject(((ChangeGameObjectStructureHierarchyEventArgs) ref hierarchyEventArgs2).instanceId) as GameObject).GetComponentInChildren<NetworkObject>() != (UnityEngine.Object) null)
          {
            flag = true;
            break;
          }
          break;
        case 2:
          ChangeGameObjectStructureEventArgs structureEventArgs;
          ((ObjectChangeEventStream) ref stream).GetChangeGameObjectStructureEvent(index, ref structureEventArgs);
          if ((UnityEngine.Object) (EditorUtility.InstanceIDToObject(((ChangeGameObjectStructureEventArgs) ref structureEventArgs).instanceId) as GameObject).GetComponentInChildren<NetworkObject>() != (UnityEngine.Object) null)
          {
            flag = true;
            break;
          }
          break;
      }
    }
    if (!flag)
      return;
    NetickEditorUtils.ConfigureNetworkSceneObjects();
  }

  private void EnsureConfigEditor()
  {
    if (!((UnityEngine.Object) this._configEditor == (UnityEngine.Object) null) && (!((UnityEngine.Object) this._configEditor != (UnityEngine.Object) null) || this._configEditor.IsValid))
      return;
    this._config = NetickEditorUtils.GetConfig();
    this._configEditor = (NetworkConfigEditor) Editor.CreateEditor((UnityEngine.Object) this._config);
    this.Repaint();
  }

  private static void LogPlayModeState(PlayModeStateChange state)
  {
    NetickWindow._selectedTab = state == 2 ? 1 : NetickWindow._selectedTab;
  }

  private static void OnHierarchyGUI(int instanceID, Rect selectionRect)
  {
    if (!Netick.Unity.Network.IsRunning || !(EditorUtility.InstanceIDToObject(instanceID) == (UnityEngine.Object) null))
      return;
    for (int index = 0; index < SceneManager.sceneCount; ++index)
    {
      Scene sceneAt = SceneManager.GetSceneAt(index);
      if (sceneAt.handle == instanceID)
      {
        NetworkSandbox networkSandbox = (NetworkSandbox) null;
        foreach (NetworkSandbox sandbox in (IEnumerable<NetworkSandbox>) Netick.Unity.Network.Sandboxes)
        {
          if (sandbox.Scene == sceneAt)
            networkSandbox = sandbox;
        }
        if ((UnityEngine.Object) networkSandbox == (UnityEngine.Object) null)
          break;
        GUI.Label(new Rect(selectionRect.xMax - 100f, selectionRect.y, 100f, selectionRect.height), networkSandbox.Name ?? "", networkSandbox.IsVisible ? EditorStyles.boldLabel : EditorStyles.miniLabel);
        break;
      }
    }
  }

  private void OnInspectorUpdate()
  {
    if (NetickWindow._selectedTab != 1)
      return;
    this.Repaint();
  }

  private void OnGUI()
  {
    if ((UnityEngine.Object) this._config == (UnityEngine.Object) null)
    {
      EditorGUILayout.HelpBox("No Netick Config file detected. Press Create Default Config.", (MessageType) 1);
      if (!GUILayout.Button("Create Default Config"))
        return;
      this._config = NetickEditorUtils.GetConfig(true);
      this.Repaint();
    }
    else
    {
      this.EnsureConfigEditor();
      string str = (NetickWindow.IsP ? " Pro" : "") ?? "";
      EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins, Array.Empty<GUILayoutOption>());
      GUILayout.Label(this._netickIcon, GUILayout.Height(70f), GUILayout.Width(300f));
      Color backgroundColor = GUI.backgroundColor;
      GUIStyle style = GUI.skin.GetStyle("HelpBox");
      style.fontSize = 12;
      style.padding = new RectOffset(10, 10, 10, 10);
      GUI.backgroundColor = Color.black;
      EditorGUILayout.LabelField($"Netick 2{str} [Beta]  —  0.14.73 ", style, Array.Empty<GUILayoutOption>());
      GUI.backgroundColor = backgroundColor;
      if ((UnityEngine.Object) this._config == (UnityEngine.Object) null)
      {
        this._config = NetickEditorUtils.GetConfig();
        UnityEngine.Object.DestroyImmediate((UnityEngine.Object) this._configEditor);
        this._configEditor = (NetworkConfigEditor) null;
      }
      if (!Application.isPlaying && GUILayout.Button("Register Scene Objects"))
        NetickEditorUtils.ConfigureNetworkSceneObjects();
      EditorGUILayout.Space(0.2f);
      NetickWindow._selectedTab = GUILayout.Toolbar(NetickWindow._selectedTab, new string[2]
      {
        "Settings",
        "Sandboxes"
      });
      EditorGUILayout.Space(3f);
      if (NetickWindow._selectedTab == 0)
      {
        this._scrollPosition = GUILayout.BeginScrollView(this._scrollPosition, false, true);
        this.EnsureConfigEditor();
        ((Editor) this._configEditor)?.OnInspectorGUI();
        GUILayout.EndScrollView();
      }
      else
        this.DrawSandboxesPanel();
      EditorGUILayout.Space(3f);
      EditorGUILayout.LabelField("\n", Array.Empty<GUILayoutOption>());
      EditorGUILayout.EndVertical();
    }
  }

  internal void DrawSandboxesPanel()
  {
    if ((UnityEngine.Object) Netick.Unity.Network.Instance == (UnityEngine.Object) null)
    {
      EditorGUILayout.Space(10f);
      EditorGUILayout.LabelField("No sandboxes are active currently.", new GUIStyle(GUI.skin.label)
      {
        alignment = TextAnchor.MiddleCenter
      }, new GUILayoutOption[1]
      {
        GUILayout.ExpandWidth(true)
      });
    }
    else
    {
      this._sandboxesCache.Clear();
      for (int index = 0; index < Netick.Unity.Network.Sandboxes.Count; ++index)
        this._sandboxesCache.Add(Netick.Unity.Network.Sandboxes[index]);
      GUIStyle guiStyle = new GUIStyle(EditorStyles.foldoutHeader);
      guiStyle.normal.textColor = Color.gray;
      if (Netick.Unity.Network.IsRunning && GUILayout.Button("Shutdown Netick"))
      {
        Netick.Unity.Network.Shutdown();
      }
      else
      {
        this._scrollPositionSand = GUILayout.BeginScrollView(this._scrollPositionSand, false, true);
        EditorGUIUtility.labelWidth = EditorGUIUtility.currentViewWidth / 3f;
        if (Netick.Unity.Network.Instance._sandboxes.Count == 0)
        {
          EditorGUILayout.Space(10f);
          EditorGUILayout.LabelField("No sandboxes are active currently.", new GUIStyle(GUI.skin.label)
          {
            alignment = TextAnchor.MiddleCenter
          }, new GUILayoutOption[1]
          {
            GUILayout.ExpandWidth(true)
          });
        }
        for (int index = 0; index < this._sandboxesCache.Count; ++index)
        {
          NetworkSandbox sandbox = this._sandboxesCache[index];
          if (!((UnityEngine.Object) sandbox == (UnityEngine.Object) null) && sandbox.Engine.IsRunning && sandbox.Engine._peer != null)
          {
            sandbox._isFolded = !EditorGUILayout.BeginFoldoutHeaderGroup(!sandbox._isFolded, sandbox.Name, sandbox.IsVisible ? EditorStyles.foldoutHeader : guiStyle, (Action<Rect>) null, (GUIStyle) null);
            if (!sandbox._isFolded)
            {
              EditorGUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
              EditorGUI.BeginDisabledGroup(Netick.Unity.Network.Instance._startMode != StartMode.MultiplePeers);
              if (GUILayout.Button(EditorGUIUtility.IconContent("ViewToolZoom")))
              {
                Netick.Unity.Network.Focus(sandbox);
                EditorApplication.RepaintHierarchyWindow();
              }
              if (GUILayout.Button(sandbox.IsVisible ? EditorGUIUtility.IconContent("animationvisibilitytoggleon") : EditorGUIUtility.IconContent("animationvisibilitytoggleoff")))
              {
                sandbox.IsVisible = !sandbox.IsVisible;
                EditorApplication.RepaintHierarchyWindow();
              }
              EditorGUI.EndDisabledGroup();
              this.DrawInputToggleButton(sandbox);
              if (GUILayout.Button(EditorGUIUtility.IconContent("winbtn_mac_close_a")))
                Netick.Unity.Network.ShutdownSandbox(sandbox);
              EditorGUILayout.EndHorizontal();
              if ((UnityEngine.Object) sandbox == (UnityEngine.Object) null || sandbox.Engine == null || sandbox.Engine._peer == null)
              {
                EditorGUILayout.EndFoldoutHeaderGroup();
                continue;
              }
              EditorGUILayout.LabelField("Mode", sandbox.Engine.StartMode.ToString(), Array.Empty<GUILayoutOption>());
              EditorGUILayout.LabelField("Player Id", sandbox.Engine.LocalPlayer.PlayerId.ToString(), Array.Empty<GUILayoutOption>());
              int num;
              if (sandbox.IsServer)
              {
                num = sandbox.Engine.Port;
                EditorGUILayout.LabelField("Port", num.ToString(), Array.Empty<GUILayoutOption>());
              }
              EditorGUILayout.LabelField("In (incoming stream)", $"{sandbox.Engine._peer.InKBps} KB/s", Array.Empty<GUILayoutOption>());
              EditorGUILayout.LabelField("Out (outgoing stream)", $"{sandbox.Engine._peer.OutKBps} KB/s", Array.Empty<GUILayoutOption>());
              if (sandbox.IsServer)
              {
                num = sandbox.Engine._server.ConnectedClients.Count;
                EditorGUILayout.LabelField("Connected Clients", num.ToString(), Array.Empty<GUILayoutOption>());
              }
              else
              {
                EditorGUILayout.LabelField("Is Connected", sandbox.IsConnected.ToString(), Array.Empty<GUILayoutOption>());
                EditorGUILayout.LabelField("RTT (round-trip time)", $"{(ValueType) (float) ((double) sandbox.Engine._profiler.RTT.Average * 1000.0):F1} ms", Array.Empty<GUILayoutOption>());
                EditorGUILayout.LabelField("Received Snapshot", $"{sandbox.Monitor.SnapshotSize.Average:F0} bytes (per tick)", Array.Empty<GUILayoutOption>());
              }
              if (index + 1 <= this._sandboxesCache.Count - 1)
                NetickWindow.DrawSeparator();
            }
            EditorGUILayout.EndFoldoutHeaderGroup();
          }
        }
        GUILayout.EndScrollView();
        this._sandboxesCache.Clear();
      }
    }
  }

  private void DrawInputToggleButton(NetworkSandbox sandbox)
  {
    Texture image = EditorGUIUtility.IconContent(sandbox.InputEnabled ? "d_PauseButton" : "d_PlayButton").image;
    if (!GUILayout.Button(new GUIContent(sandbox.InputEnabled ? "Disable Input" : "Enable Input", image)))
      return;
    sandbox.InputEnabled = !sandbox.InputEnabled;
  }

  private static void DrawSeparator(float thickness = 1f, float padding = 6f)
  {
    Color color = EditorGUIUtility.isProSkin ? new Color(1f, 1f, 1f, 0.1f) : new Color(0.0f, 0.0f, 0.0f, 0.2f);
    GUILayout.Space(padding);
    EditorGUI.DrawRect(GUILayoutUtility.GetRect(1f, thickness, GUILayout.ExpandWidth(true)), color);
    GUILayout.Space(padding);
  }
}
